package com.rabbit.utils;

import com.rabbit.constants.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * RabbitMq工具类
 *
 * @author kh
 */
@Slf4j
@Component
public class RabbitMqUtil {
    @Resource
    private RabbitAdmin rabbitAdmin;

    public boolean createQueue(String queueName) {
        if (queueName == null) {
            return false;
        }
        if (queueExists(queueName)) {
            return true;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("x-dead-letter-exchange", RabbitConstant.Exchange.DEAD_EXCHANGE);
        map.put("x-message-ttl", Integer.parseInt(RabbitConstant.Other.MESSAGE_TTL));
        Queue queue = new Queue(queueName, true, false, false, map);
        try {
            String result = rabbitAdmin.declareQueue(queue);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 删除队列
     *
     * @param queueName
     * @param unused    队列是否在使用，为true时只能在没有被使用的情况下才能删除
     * @param empty     队列是否为空，为true时只能在队列没有消息时才能删除
     * @return true 删除成功 false 删除失败
     */
    public boolean deleteQueue(String queueName, boolean unused, boolean empty) {
        if (queueName == null) {
            return false;
        }
        rabbitAdmin.deleteQueue(queueName, false, true);
        return queueExists(queueName) ? false : true;
    }

    /**
     * 队列是否存在
     *
     * @param queueName
     * @return true 存在 false 不存在
     */
    public boolean queueExists(String queueName) {
        if (queueName == null) {
            return false;
        }
        String exists = rabbitAdmin.getRabbitTemplate().execute((channel -> {
            try {
                return channel.queueDeclarePassive(queueName).getQueue();
            } catch (Exception e) {
                log.error(e.getMessage());
                return null;
            }
        }));
        return exists != null ? true : false;
    }

    /**
     * 创建交换器
     *
     * @param exchangeName
     * @param exchangeTye  交换器类型 Constant.EXCHANGE_TYPE
     * @return
     */
    public boolean createExchange(String exchangeName, String exchangeTye) {
        if (exchangeName == null) {
            return false;
        }
        Exchange exchange = null;
        if (RabbitConstant.ExchangeType.EXCHANGE_TYPE_DIRECT.equalsIgnoreCase(exchangeTye)) {
            exchange = new DirectExchange(exchangeName, true, false);
        } else if (RabbitConstant.ExchangeType.EXCHANGE_TYPE_FANOUT.equalsIgnoreCase(exchangeTye)) {
            exchange = new FanoutExchange(exchangeName, true, false);
        } else if (RabbitConstant.ExchangeType.EXCHANGE_TYPE_HEADER.equalsIgnoreCase(exchangeTye)) {
            exchange = new HeadersExchange(exchangeName, true, false);
        } else if (RabbitConstant.ExchangeType.EXCHANGE_TYPE_TOPIC.equalsIgnoreCase(exchangeTye)) {
            exchange = new TopicExchange(exchangeName, true, false);
        } else if (RabbitConstant.ExchangeType.EXCHANGE_TYPE_DELAYED.equalsIgnoreCase(exchangeTye)) {
            Map<String, Object> pros = new HashMap<>();
            pros.put("x-delayed-type", RabbitConstant.ExchangeType.EXCHANGE_TYPE_TOPIC);
            exchange = new CustomExchange(exchangeName, "x-delayed-message", true, false, pros);
        }
        try {
            rabbitAdmin.declareExchange(exchange);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 删除交换器
     *
     * @param exchangeName
     * @return
     */
    public boolean deleteExchange(String exchangeName) {
        if (exchangeName == null) {
            return false;
        }
        return rabbitAdmin.deleteExchange(exchangeName);
    }

    /**
     * 队列绑定交换器
     *
     * @param routingKey
     * @param queueName
     * @param exchangeName
     * @return
     */
    public boolean queueBinding(String routingKey, String queueName, String exchangeName) {
        Binding binding = new Binding(queueName, Binding.DestinationType.QUEUE, exchangeName, routingKey, null);
        try {
            rabbitAdmin.declareBinding(binding);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 交换器绑定交换器
     *
     * @param routingKey
     * @param bindingExchange 需绑定的交换器
     * @param exchange        被绑定的交换器
     * @return
     */
    public boolean exchangeBinding(String routingKey, String bindingExchange, String exchange) {
        Binding binding = new Binding(bindingExchange, Binding.DestinationType.EXCHANGE, exchange, routingKey, null);
        try {
            rabbitAdmin.declareBinding(binding);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 移除绑定
     *
     * @param routingKey
     * @param unbind
     * @param exchange
     * @return
     */
    public boolean removeBinding(String routingKey, String unbind, String exchange) {
        Binding binding = new Binding(unbind, Binding.DestinationType.QUEUE, exchange, routingKey, null);
        try {
            rabbitAdmin.removeBinding(binding);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

}
